package main

import (
	"fmt"
	"sync"
)

var wg = sync.WaitGroup{}

type safeData struct {
	content map[int]int
	//读写锁
	lock sync.RWMutex
}

func (m *safeData) addEntity(k int) {
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("出错啦, k=%d, %v\n", k, r)
		} else {
			fmt.Println("已添加,k= ", k)
		}
		//代表一次结束
		wg.Done()
	}()

	m.lock.Lock()
	//fatal error: all goroutines are asleep - deadlock!
	//此处产生/0的异常后，即使捕获成功，锁也不会释放，因此后续代码会产生死锁，进而导致程序非正常退出
	m.content[k] = k / (k - 10)
	m.lock.Unlock()
}

func (m *safeData) addEntitySafe(k int) {
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("出错啦, k=%d, %v\n", k, r)
		} else {
			fmt.Println("已添加,k= ", k)
		}
		//代表一次结束
		wg.Done()
	}()

	m.lock.Lock()
	//当出现多个defer语句时，函数会被放入一个后进先出的栈中，因此后声明的函数会先执行。
	//先定义释放语句，方便再程序出错时，延迟队列中的操作依旧会被调用
	//这条语句由于后进先出原则，会在函数执行完后立刻执行
	defer m.lock.Unlock()
	m.content[k] = k / (k - 10)
}

func main() {
	data := safeData{}
	wg.Add(10)
	//容量为10的map
	data.content = make(map[int]int, 10)
	for i := 1; i <= 10; i++ {
		go func(ii int) {
			data.addEntitySafe(ii)
		}(i)
	}
	//等待组内所有协程执行完毕
	wg.Wait()
}
